package com.mrli.cat.weather.service;

import android.accounts.Account;
import android.content.AbstractThreadedSyncAdapter;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SyncResult;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;

import com.google.gson.Gson;
import com.mrli.cat.weather.activity.ForecastFragment;
import com.mrli.cat.weather.activity.WeatherPreferenceActivity;
import com.mrli.cat.weather.database.WeatherContract;
import com.mrli.cat.weather.model.OpenWeatherMapBean;
import com.mrli.cat.weather.tools.Constant;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;

public class SyncAdapter extends AbstractThreadedSyncAdapter {
    public static final String TAG = SyncAdapter.class.getName();
    private ContentResolver mContentResolver;
    private Context mContext;

    public SyncAdapter(Context context, boolean autoInitialize) {
        super(context, autoInitialize);
        this.mContentResolver = context.getContentResolver();
        this.mContext = context;
    }

    public SyncAdapter(Context context, boolean autoInitialize, boolean allowParallelSyncs, ContentResolver mContentResolver) {
        super(context, autoInitialize, allowParallelSyncs);
        this.mContentResolver = mContentResolver;
        this.mContext = context;
    }

    @Override
    public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
        LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(getContext());
        Intent startIntent = new Intent(ForecastFragment.ACTION_SYNC_START);
        Intent doneIntent = new Intent(ForecastFragment.ACTION_SYNC_DONE);
        Intent falseIntent = new Intent(ForecastFragment.ACTION_SYNC_FALSE);
        localBroadcastManager.sendBroadcast(startIntent);
        Uri uri = Uri.parse(Constant.OpenWeatherMap.AUTHORITY + Constant.OpenWeatherMap.PATH);
        //获取数据库有关城市的详细信息, 并构建Uri
        Cursor cursor = getDetailCityInfo();
        if (cursor == null) {
            localBroadcastManager.sendBroadcast(falseIntent);
        }
        if (cursor.moveToFirst()) {
            uri = uri.buildUpon()
                    .appendQueryParameter(Constant.OpenWeatherMap.QUERY_LAT, String.valueOf(cursor.getDouble(cursor.getColumnIndex(WeatherContract.LocationEntry.COLUMN_LAT))))
                    .appendQueryParameter(Constant.OpenWeatherMap.QUERY_LON, String.valueOf(cursor.getDouble(cursor.getColumnIndex(WeatherContract.LocationEntry.COLUMN_LON))))
                    .appendQueryParameter(Constant.OpenWeatherMap.QUERY_MODE, Constant.OpenWeatherMap.MODE)
                    .appendQueryParameter(Constant.OpenWeatherMap.QUERY_UNITS, Constant.OpenWeatherMap.UNITS)
                    .appendQueryParameter(Constant.OpenWeatherMap.QUERY_CNT, String.valueOf(Constant.OpenWeatherMap.MAX_FORECAST_DAY))
                    .appendQueryParameter(Constant.OpenWeatherMap.QUERY_CODE, Constant.OpenWeatherMap.CODE)
                    .build();
        }
        HttpURLConnection connection = null;
        BufferedReader chreader = null;
        try {
            URL url = new URL(uri.toString());
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            InputStream in = connection.getInputStream();
            InputStreamReader inreader = new InputStreamReader(in);
            chreader = new BufferedReader(inreader);
            String line = null;
            StringBuffer stringBuffer = new StringBuffer();
            while ((line = chreader.readLine()) != null) {
                stringBuffer.append(line + "\n");
            }
            //解析收到的JSON
            writeContentProvider(stringBuffer.toString(), cursor.getInt(cursor.getColumnIndex(WeatherContract.LocationEntry._ID)));
        } catch (MalformedURLException e) {
            e.printStackTrace();
            localBroadcastManager.sendBroadcast(falseIntent);
        } catch (ProtocolException e) {
            e.printStackTrace();
            localBroadcastManager.sendBroadcast(falseIntent);
        } catch (IOException e) {
            e.printStackTrace();
            localBroadcastManager.sendBroadcast(falseIntent);
        } finally {
            if (chreader != null) {
                try {
                    chreader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                connection.disconnect();
            }
            if (cursor != null && !cursor.isClosed())
                cursor.close();
        }
        localBroadcastManager.sendBroadcast(doneIntent);
    }

    public void writeContentProvider(String jsonstr, int cityID) {
        Gson gson = new Gson();
        OpenWeatherMapBean bean = gson.fromJson(jsonstr, OpenWeatherMapBean.class);
        if (bean != null) {
            SharedPreferences sharedPreferences = getContext().getSharedPreferences(ForecastFragment.INIT_SHAREDPREFERENCE, Context.MODE_PRIVATE);
            if (sharedPreferences.getBoolean(WeatherPreferenceActivity.INIT_KEY, true)) {
                init(bean, cityID);
                sharedPreferences.edit().putBoolean(WeatherPreferenceActivity.INIT_KEY, false).commit();
            }
            //删除冗余的数据
            getContext().getContentResolver().delete(
                    WeatherContract.WEATHER_CONTENT_URI,
                    WeatherContract.WeatherEntry.COLUMN_CITY_ID + "=?",
                    new String[]{String.valueOf(cityID)}
            );
            init(bean, cityID);
        } else {
            //出现错误
            Log.d("TAG", "writeToContentProvider Error");
        }
    }

    /**
     * 根据配置文件中的定位信息, 从服务器获取城市的详细信息
     *
     * @return
     */
    public Cursor getDetailCityInfo() {
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
        String cityName = sharedPreferences.getString(WeatherPreferenceActivity.LOCAL_CITY, "");
        Cursor cursor = mContentResolver.query(
                WeatherContract.LOCATION_CONTENT_URI,
                null,
                WeatherContract.LocationEntry.COLUMN_NAME + "= ?",
                new String[]{cityName},
                null);
        return cursor;
    }

    public ContentValues fillValue(OpenWeatherMapBean.ListEntity bean, int id) {
        ContentValues values = new ContentValues();
        values.put(WeatherContract.WeatherEntry.COLUMN_CITY_ID, id);
        values.put(WeatherContract.WeatherEntry.COLUMN_WEATHER, bean.getWeather().get(0).getId());
        values.put(WeatherContract.WeatherEntry.COLUMN_TIME, bean.getDt());
        values.put(WeatherContract.WeatherEntry.COLUMN_TEMP_MAX, bean.getTemp().getMax());
        values.put(WeatherContract.WeatherEntry.COLUMN_TEMP_MIN, bean.getTemp().getMin());
        values.put(WeatherContract.WeatherEntry.COLUMN_HUMI, bean.getHumidity());
        values.put(WeatherContract.WeatherEntry.COLUMN_PRESSURE, bean.getPressure());
        values.put(WeatherContract.WeatherEntry.COLUMN_WIND_SPEED, bean.getSpeed());
        values.put(WeatherContract.WeatherEntry.COLUMN_WIND_DEG, bean.getDeg());
        return values;
    }

    /**
     * 初始化数据库
     *
     * @param bean
     */
    public void init(OpenWeatherMapBean bean, int id) {
        if (bean != null) {
            ContentValues[] bulk = new ContentValues[bean.getList().size()];
            for (int i = 0; i < bulk.length; i++) {
                bulk[i] = fillValue(bean.getList().get(i), id);
            }
            getContext().getContentResolver().bulkInsert(WeatherContract.WEATHER_CONTENT_URI, bulk);
        }
    }
}
